<?php
	/*
	修改：
	fetchRows 方法
		增加判断已带where的情况
	*/
class LtDb
{
	static public $connection;

	private $tableName;

	private $conf;

	private $fields;

	private $primaryKey = 'id';

	public function __construct($table)
	{
		$this->conf = LtObjectUtil::singleton("LtConfig")->get('db');
		$this->tableName = $this->conf['prefix'].$table;
	}
	
	public function table($table){
		return $this->conf['prefix'].$table;
	}
	
	public function count($args)
	{
		$selectTemplate = 'SELECT COUNT(*) AS total FROM %s%s';
		
		$where = $this->where($args);
		$sql = sprintf($selectTemplate, $this->tableName, $where);

		$queryResult = $this->_select($sql);
		return $queryResult[0]['total'];
	}

	public function delete($primaryKeyId)
	{
		$args[$this->primaryKey] = $primaryKeyId;

		return $this->deleteRows($args);
	}

	public function deleteRows($args = null)
	{
		$deleteTemplate = 'DELETE FROM %s%s';
		//south 2012-03-18 没有where解析不正常
		if (is_array($args)  && !isset($args['where']))
		{
			$args['where'] = $args;
		}
		$where = $this->where($args);
		$sql = sprintf($deleteTemplate, $this->tableName, $where);
		return $this->_delete($sql);
	}

	public function get($primaryKeyId)
	{
		$args[$this->primaryKey] = $primaryKeyId;
		$fetchResult = $this->fetchRows('',$args,'','');
		return $fetchResult ? $fetchResult[0] : $fetchResult;
	}

	public function fetch($fields='',$where='',$join='',$orderby='')
	{
		$list = $this->fetchRows($fields, $where, $join, $orderby, 1);

		if(empty($list))
		{
			return false;
		}

		return $list[0];
	}

	public function fetchRows($fields='',$where='',$join='',$orderby='',$limit='',$start=0)
	{
		$args = array();
		if(empty($fields))
		{
			$fields = '*';
		}
		else
		{
			$fields = implode(',',$fields);
		}
		$args['fileds']	= $fields;
		
		//south 增加已带where的情况
		if (is_array($where)  && isset($where['where']))
		{
			$args['where'] = $where['where'];
		}elseif(!empty($where))
		{
			$args['where'] = $where;
		}

		if(!empty($join))
		{
			$args['join'] = $join;
		}

		if(!empty($orderby))
		{
			$args['orderby'] = $orderby;
		}

		if(!empty($limit))
		{
			$args['limit'] = $limit;
		}

		if(is_numeric($start))
		{
			$args['offset'] = $start;
		}

		$selectTemplate = 'SELECT '.$fields.' FROM %s%s';
		$where = $this->where($args);
		$sql = sprintf($selectTemplate, $this->tableName, $where);
		
		return $this->_select($sql);
	}

	public function query($fields='',$where='',$join='',$orderby='',$limit='',$start=0)
	{
		$result = array();
		$result['count'] = $this->count($where);
		if($result['count']>0)
		{
			$result['rows'] = $this->fetchRows($fields, $where, $join, $orderby, $limit, $start);
		}

		return $result;
	}

	public function insert($args = null)
	{
		//设置记录添加时间
		if(!array_key_exists('created',$args))
		{
			$args['created'] = date('Y-m-d H:i:s');
		}
		
		$this->buildFieldList();
		
		$fields = array();
		$placeHolders = array();
		$conn = $this->getConnection();
		foreach($args as $field => $value)
		{
			if (array_key_exists($field, $this->fields))
			{
				$fields[] = $field;
				$values[] = "'" . mysql_real_escape_string($value, $conn) . "'";
			}
		}
		
		$insertTemplate = 'INSERT INTO %s (%s) VALUES (%s)';
		$sql = sprintf($insertTemplate, $this->tableName, implode(",", $fields), implode(",", $values));
		
		$queryResult = $this->_insert($sql);
		return isset($args[$this->primaryKey]) ? $args[$this->primaryKey] : $queryResult;
	}

	public function update($primaryKeyId, $args)
	{
		$con[$this->primaryKey] = $primaryKeyId;

		return $this->updateRows($con, $args);
	}

	public function updateRows($where, $args)
	{
		$this->buildFieldList();
		
		$fields = array();
		$conn = $this->getConnection();
		foreach($args as $field => $value)
		{
			if (array_key_exists($field, $this->fields))
			{
				if (strpos($args[$field],'expression:')===0)
				{
					$fields[] = "$field=" . substr($args[$field], 11);
				}
				else
				{
					$fields[] = "$field='" . mysql_real_escape_string($value, $conn) . "'";;
				}
			}
		}

		$updateTemplate = 'UPDATE %s SET %s %s';
		$where = $this->where($where);
		
		$sql = sprintf($updateTemplate, $this->tableName, implode(",", $fields), $where);
		
		return $this->_update($sql);
	}
	
	public function execute($sql)
	{
		return $this->_exec($sql, $this->getConnection());
	}
	
	public function select($sql)
	{
		return $this->_select($sql, $this->getConnection());
	}

	private function _select($sql)
	{//	echo $sql."<br/>";
		$result = mysql_query($sql, $this->getConnection());
		$rows = array();
		while($row = mysql_fetch_assoc($result))
		{
			$rows[] = $row;
		}
		return $rows;
	}

	private function _insert($sql)
	{
		$conn = $this->getConnection();
		if ($result = $this->_exec($sql, $conn))
		{
			return mysql_insert_id($conn);
		}
		else
		{
			return $result;
		}
	}

	private function _update($sql)
	{
		return false === $this->_exec($sql, $this->getConnection()) ? false : true;
	}

	private function _delete($sql)
	{
		return false === $this->_exec($sql, $this->getConnection()) ? false : true;
	}

	private function _exec($sql,$conn)
	{
		if (mysql_query($sql, $conn)){
			return mysql_affected_rows($conn);
		}
		file_put_contents('error.sql', $sql.'=>'.mysql_error(),FILE_APPEND);
		return false;
	}

	private function where($con)
	{
		$conn = $this->getConnection();
		
		$values		= array();
		$expression = array();
		if(!empty($con['where']))
		{
			foreach($con['where'] as $k=>$v)
			{
				if(is_array($v))
				{
					if(array_key_exists('in', $v))
					{
						$expression[]	= $k.' in (:'.$k.')';
						$values[$k]		= $v['in'];
					}
					else if(array_key_exists('between', $v))
					{
						$vv = $v['between'];
		
						$exp = array();
		
						if(array_key_exists('le', $vv))
						{
							$exp[] = $k.' <= :le_'.$k;
							$values['le_'.$k] = $vv['le'];
						}
						if(array_key_exists('lt', $vv))
						{
							$exp[] = $k.' < :lt_'.$k;
							$values['lt_'.$k] = $vv['lt'];
						}
						if(array_key_exists('ge', $vv))
						{
							$exp[] = $k.' >= :ge_'.$k;
							$values['ge_'.$k] = $vv['ge'];
						}
						if(array_key_exists('gt', $vv))
						{
							$exp[] = $k.' > :gt_'.$k;
							$values['gt_'.$k] = $vv['gt'];
						}
		
						$expression[] = implode(' AND ', $exp);
					}
				}
				else if(is_numeric($v) || strpos($v,'eq:')===0)
				{
					if(strpos($v,'eq:')===0)
					{
						$v = substr($v, 3);
					}
					$expression[]	= $k.'=:'.$k;
					$values[$k]		= $v;
				}
				else
				{
					$expression[]	= $k.' like :'.$k;
					$values[$k]		= '%'.$v.'%';
				}
			}
		}
		
		$where = implode(' AND ',$expression);
		if(!empty($where))
		{
			$where = ' WHERE '.$where;
		}
		$join = isset($con['join']) ? ' ' . $con['join'] : '';
		$orderby = isset($con['orderby']) ? ' ORDER BY ' . $con['orderby'] : '';
		$groupby = isset($con['groupby']) ? ' GROUP BY ' . $con['groupby'] : '';
		$limit = '';
		if (isset($con['limit']))
		{
			$offset = isset($con['offset']) ? $con['offset'] : 0;
			$limit = ' limit '.$offset.','.$con['limit'];
		}
		
		$sql = $join . $where . $groupby . $orderby. $limit;
		
		if (is_array($values) && 0 < count($values))
		{
			//绑定参数
			$sql = preg_replace("/:([a-zA-Z0-9_\-\x7f-\xff][a-zA-Z0-9_\-\x7f-\xff]*)\s*([,\)]?)/", "\x01\x02\x03\\1\x01\x02\x03\\2 ", $sql);
			foreach($values as $key => $value)
			{
				$find[] = "\x01\x02\x03$key\x01\x02\x03";
				if (strpos($value,'expression:')===0)
				{
					$replacement[] = substr($value, 11);
				}
				else if(is_array($value))
				{
					$tmp = array();
					foreach($value as $vv)
					{
						$tmp[] = "'" . mysql_real_escape_string($vv, $conn) . "'";
					}
					$replacement[] = implode(',', $tmp);
				}
				else
				{
					$replacement[] = "'" . mysql_real_escape_string($value, $conn) . "'";
				}
			}
			$sql = str_replace($find, $replacement, $sql);
		}
		
		return $sql;
	}

	private function getConnection()
	{

		if(self::$connection!=null)
		{
			return self::$connection;
		}
		$conn = @mysql_connect($this->conf["host"] . ":" . $this->conf["port"], $this->conf["user"], $this->conf["pass"]);
		if(!$conn)
		{
			return false;
		}
		self::$connection = $conn;
		$this->_exec('USE '.$this->conf['dbname'], $conn);
		$this->_exec('SET NAMES '.$this->conf['charset'], $conn);

		return self::$connection;
	}

	private function buildFieldList()
	{
		if (!empty($this->fields))
		{
			return;
		}

		$sql = 'DESCRIBE '.$this->tableName;
		$tmp = $this->_select($sql);
		$this->fields = $this->getFields($tmp);
		foreach($this->fields as $field)
		{
			if ($field['primary'] == 1)
			{
				$this->primaryKey = $field['name'];
				break;
			}
		}
	}

	private function getFields($data)
	{
		$result = array();
		foreach($data as $field)
		{
			$f = array('name'=>$field['Field'],'primary'=>$field['Key'] == 'PRI'?1:0);
			$result[$field['Field']] = $f;
		}
		return $result;
	}
}